#include "config.h"

#include <iostream>
#include <memory>
#include <string>
#include <vector>
#if CFG_HAVE_STD_RANGES
#include <ranges>
#endif

using namespace cfg;

// 作用：将错误列表以可读的形式输出到标准输出，包含错误码、路径与消息。
// 参数：
//   errs - 冻结/校验阶段收集到的错误数组。
// 返回：无。
static void
print_error_list(const std::vector<ConfigError> & errs)
{
    std::cout << "Errors: " << errs.size() << "\n";
    for (const auto & e : errs)
    {
        std::cout << "  - code=" << static_cast<int>(e.code) << ", path=";
        if (e.path.empty())
            std::cout << "<root>";
        // 使用 join_with 拼接路径，避免手写下标判断
        if (!e.path.empty())
        {
#if CFG_HAVE_STD_RANGES
            for (char ch : e.path | std::views::join_with(std::string_view(".")))
            {
                std::cout << ch;
            }
#else
            for (size_t i = 0; i < e.path.size(); ++i)
            {
                if (i > 0)
                    std::cout << '.';
                std::cout << e.path[i];
            }
#endif
        }
        std::cout << ", message=" << e.message << "\n";
    }
}

// 作用：构造一个源对象，形如：
//   { db: { host: "new", opts: { timeout: 30 } } }
// 用于合并演示。
// 参数：无。
// 返回：cfg::Object 源对象。
static Object
make_src_db_object()
{
    Object src_db;
    src_db.props["host"] = std::string("new");

    Object src_opts;
    src_opts.props["timeout"] = int64_t(30);
    src_db.props["opts"] = std::shared_ptr<const Object>(std::make_shared<Object>(src_opts));

    Object src_root;
    src_root.props["db"] = std::shared_ptr<const Object>(std::make_shared<Object>(src_db));
    return src_root;
}

// 作用：演示“深合并 + 覆盖”策略下的对象合并结果。
// 行为：
//  - 覆盖 db.host -> "new"
//  - 保留 db.opts.pool -> 10
//  - 新增 db.opts.timeout -> 30
// 返回：无。
static void
run_deep_merge_overwrite_scenario()
{
    std::cout << "[Scenario] Deep merge + Overwrite\n";

    Builder b;
    b.set("db.host", std::string("old"));
    b.set("db.opts.pool", int64_t(10));
    b.set_merge_strategy(MergeStrategy::Deep).set_conflict_policy(ConflictPolicy::Overwrite);

    Object src = make_src_db_object();
    b.merge_object(src);

    auto fr = b.freeze();
    if (!fr.has_value())
    {
        print_error_list(fr.error());
        return;
    }
    View v(*fr);

    auto host = v.lookup("db.host");
    auto pool = v.lookup("db.opts.pool");
    auto timeout = v.lookup("db.opts.timeout");
    // host 输出：类型不匹配显示占位
    if (host.has_value())
    {
        auto hs = host->get_string();
        std::cout << "db.host=" << (hs.has_value() ? *hs : std::string("<type-mismatch>")) << "\n";
    }
    else
    {
        std::cout << "db.host=<missing>\n";
    }
    // pool/timeout 输出：类型不匹配使用 -1 占位
    if (pool.has_value())
    {
        auto pv = pool->get_int64();
        std::cout << "db.opts.pool=" << std::to_string(pv.has_value() ? pv.value() : int64_t(-1))
                  << "\n";
    }
    else
    {
        std::cout << "db.opts.pool=<missing>\n";
    }
    if (timeout.has_value())
    {
        auto tv = timeout->get_int64();
        std::cout << "db.opts.timeout=" << std::to_string(tv.has_value() ? tv.value() : int64_t(-1))
                  << "\n";
    }
    else
    {
        std::cout << "db.opts.timeout=<missing>\n";
    }
}

// 作用：演示“浅合并 + 覆盖”策略下的对象合并结果。
// 行为：
//  - 整个 db 被源覆盖：host->"new"，opts.pool 消失，opts.timeout 存在。
// 返回：无。
static void
run_shallow_merge_overwrite_scenario()
{
    std::cout << "[Scenario] Shallow merge + Overwrite\n";

    Builder b;
    b.set("db.host", std::string("old"));
    b.set("db.opts.pool", int64_t(10));
    b.set_merge_strategy(MergeStrategy::Shallow).set_conflict_policy(ConflictPolicy::Overwrite);

    Object src = make_src_db_object();
    b.merge_object(src);

    auto fr = b.freeze();
    if (!fr.has_value())
    {
        print_error_list(fr.error());
        return;
    }
    View v(*fr);

    auto host = v.lookup("db.host");
    auto pool = v.lookup("db.opts.pool");
    auto timeout = v.lookup("db.opts.timeout");
    if (host.has_value())
    {
        auto hs = host->get_string();
        std::cout << "db.host=" << (hs.has_value() ? *hs : std::string("<type-mismatch>")) << "\n";
    }
    else
    {
        std::cout << "db.host=<missing>\n";
    }
    if (pool.has_value())
    {
        auto pv = pool->get_int64();
        std::cout << "db.opts.pool=" << std::to_string(pv.has_value() ? pv.value() : int64_t(-1))
                  << "\n";
    }
    else
    {
        std::cout << "db.opts.pool=<missing>\n";
    }
    if (timeout.has_value())
    {
        auto tv = timeout->get_int64();
        std::cout << "db.opts.timeout=" << std::to_string(tv.has_value() ? tv.value() : int64_t(-1))
                  << "\n";
    }
    else
    {
        std::cout << "db.opts.timeout=<missing>\n";
    }
}

// 作用：演示“冲突策略=Keep”下的覆盖冲突处理，保留旧值。
// 行为：
//  - 先写 a=1，再合并 a=2，结果仍为 1。
// 返回：无。
static void
run_conflict_keep_scenario()
{
    std::cout << "[Scenario] ConflictPolicy::Keep\n";

    Builder b;
    b.set("a", int64_t(1));

    Object src;
    src.props["a"] = int64_t(2);

    b.set_merge_strategy(MergeStrategy::Shallow)
        .set_conflict_policy(ConflictPolicy::Keep)
        .merge_object(src);

    auto fr = b.freeze();
    if (!fr.has_value())
    {
        print_error_list(fr.error());
        return;
    }
    View v(*fr);
    auto a = v.lookup("a");
    if (a.has_value())
    {
        auto av = a->get_int64();
        std::cout << "a=" << std::to_string(av.has_value() ? av.value() : int64_t(-1)) << "\n";
    }
    else
    {
        std::cout << "a=<missing>\n";
    }
}

// 作用：演示“冲突策略=Error”下的覆盖冲突处理，记录错误并冻结失败。
// 行为：
//  - 先写 a=1，再合并 a=2，结果冻结返回错误列表，包含冲突信息。
// 返回：无。
static void
run_conflict_error_scenario()
{
    std::cout << "[Scenario] ConflictPolicy::Error\n";

    Builder b;
    b.set("a", int64_t(1));

    Object src;
    src.props["a"] = int64_t(2);

    b.set_merge_strategy(MergeStrategy::Shallow)
        .set_conflict_policy(ConflictPolicy::Error)
        .merge_object(src);

    auto fr = b.freeze();
    if (!fr.has_value())
    {
        print_error_list(fr.error());
        return;
    }
    std::cout << "<unexpected success>\n";
}

// 作用：程序入口，按顺序演示对象合并与冲突策略的典型场景。
// 参数：
//   argc/argv - 保留未用。
// 返回：进程退出码，0 表示成功。
int
main(int /*argc*/, char * /*argv*/[])
{
    run_deep_merge_overwrite_scenario();
    std::cout << "---\n";
    run_shallow_merge_overwrite_scenario();
    std::cout << "---\n";
    run_conflict_keep_scenario();
    std::cout << "---\n";
    run_conflict_error_scenario();
    return 0;
}
